#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define SERVERPORT 8888
#define MAX_EVENTS 10
#define BUFFER_SIZE 1024

typedef struct Epoll_t Epoll_t;
typedef void (*EpollCallback)(Epoll_t*, int);
typedef struct EpollItem_t
{
    int           fd;
    uint32_t      event;
    EpollCallback callback;
} EpollItem_t;

typedef struct Epoll_t
{
    int          epoll_fd;
    EpollItem_t* items;
    int          items_max;
    int          items_count;
} Epoll_t;

int epoll_init(Epoll_t* epoll) {
    // 创建 epoll 实例
    epoll->epoll_fd = epoll_create1(0);
    if (epoll->epoll_fd == -1) {
        perror("epoll_create1");
        exit(1);
    }

    epoll->items_max   = 20;
    epoll->items_count = 0;
    epoll->items       = malloc(sizeof(EpollItem_t) * epoll->items_max);
    return 0;
}

static int __epoll_add_item(Epoll_t* epoll, EpollItem_t* item) {
    if (epoll->items_count >= epoll->items_max) {
        int temp_size = epoll->items_max * 2;

        void* p = malloc(sizeof(EpollItem_t) * temp_size);
        if (p == NULL) {
            perror("epoll_addItem");
            return -1;
        }
        memcpy(p, epoll->items, sizeof(EpollItem_t) * epoll->items_count);
        free(epoll->items);
        epoll->items     = p;
        epoll->items_max = temp_size;
    }

    memcpy(&epoll->items[epoll->items_count++], item, sizeof(EpollItem_t));

    // 将 socket 加入 epoll 实例中
    struct epoll_event event;
    event.events  = item->event;
    event.data.fd = item->fd;
    if (epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, item->fd, &event) == -1) {
        perror("epoll_ctl");
        return -1;
    }
    return 0;
}

int epoll_add_item(Epoll_t* epoll, int fd, EpollCallback callback) {
    EpollItem_t item;
    item.fd       = fd;
    item.callback = callback;
    item.event    = EPOLLIN;
    return __epoll_add_item(epoll, &item);
}

int epoll_remove_item(Epoll_t* epoll, int fd) {
    epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
    for (int i = 0; i < epoll->items_count; i++) {
        if (epoll->items[i].fd == fd) {
            memcpy(&epoll->items[i], &epoll->items[epoll->items_count-1], sizeof(EpollItem_t));
            epoll->items_count--;
        }
    }
}

void epoll_exec(Epoll_t* epoll) {
    struct sockaddr_in client_addr;
    socklen_t          client_len;
    char               buffer[BUFFER_SIZE];

    // 处理事件循环
    struct epoll_event events[MAX_EVENTS];
    while (1) {
        int num_ready = epoll_wait(epoll->epoll_fd, events, MAX_EVENTS, -1);
        if (num_ready == -1) {
            perror("epoll_wait");
            exit(1);
        }
        for (int i = 0; i < num_ready; ++i) {
            for (int j = 0; j < epoll->items_count; j++) {
                if (events[i].data.fd == epoll->items[j].fd) {
                    printf("ready is:%d\n", j);
                    epoll->items[j].callback(epoll, epoll->items[j].fd);
                }
            }
        }
    }
}
